iT邦幫忙

2024 iThome 鐵人賽

DAY 4
0

接者來快速做一個應用來串接 Keycloak 的登入試試,這邊用的是基於 Nextjs 的 T3

pnpm create t3-app@latest

在建立的時候注意要選使用 NextAuth

https://res.cloudinary.com/dhcsjvhjg/image/upload/v1726649517/Screenshot_2024-09-18_at_4.50.54_PM_xijzbk.png

這邊用的是 Prisma 作為 ORM 搭配 Postgres,專案生成後首先建立資料庫的 Docker 跟將預設的 Schema 同步進去。

bash start-database.sh
pnpm db:push

接下來要設定 NextAuth 使用 Keycloak 登入,官方有對應的 provider 可以使用。

// src/server/auth.ts
import KeycloakProvider from "next-auth/providers/keycloak";

// ...

export const authOptions: NextAuthOptions = {
  callbacks: {
    session: ({ session, user }) => ({
      ...session,
      user: {
        ...session.user,
        id: user.id,
      },
    }),
  },
  adapter: PrismaAdapter(db) as Adapter,
  providers: [
    KeycloakProvider({
      clientId: env.KEYCLOAK_CLIENT_ID!,
      clientSecret: env.KEYCLOAK_CLIENT_SECRET!,
      issuer: env.KEYCLOAK_ISSUER,
    }),
  ],
};

環境變數參考如下:

KEYCLOAK_ISSUER="http://localhost:8080/realms/awesome" # 執行驗證的 realm 端口
KEYCLOAK_CLIENT_ID="awesome-next"
KEYCLOAK_CLIENT_SECRET="*************************"

KEYCLOAK_CLIENT_SECRET 可以在 Client 中 的 Credential 頁面找到

https://res.cloudinary.com/dhcsjvhjg/image/upload/v1726651252/Screenshot_2024-09-18_at_5.19.31_PM_mrac0n.png

準備好登入端口後再來啟動專案

pnpm dev

就能試著來用 Keycloak 做登入了

https://res.cloudinary.com/dhcsjvhjg/image/upload/v1726653890/Screenshot_2024-09-18_at_6.04.42_PM_r6kbyt.png

點下去會導向 Keycloak 自己的登入頁面,在那邊登入成功後導向回 Next App 後就會是登入成功的狀態了。

但這邊會有個問題,Keycloak Provider 回傳的 user data 沒有跟 NextAuth 的 Account 資訊對齊,在用 Prisma 寫入時會報錯,所以要做點調整。

// src/server/auth.ts
const adapter = PrismaAdapter(db);
const _linkAccount = adapter.linkAccount;
adapter.linkAccount = (account) => {
	// 將沒對上的參數濾出或替換
  const { "not-before-policy": _, refresh_expires_in, ...data } = account;
  return _linkAccount!({
    ...data,
    refresh_token_expires_in: refresh_expires_in,
  });
};

上一篇
身份驗證 - Keycloak
下一篇
同步登出 NextJs 跟 Keycloak
系列文
Awesome self hosted 30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言